/*
 *   This file is part of <open-parametrics>
 *   Copyright (c) 2006-2008 Miguel-Angel Sicilia
 *
 *   open-parametrics is free software: you can redistribute it and/or modify
 *   it under the terms of the Lesser GNU General Public License as
 *   published by the Free Software Foundation, either version 3 of
 *   the License, or (at your option) any later version.
 *
 *   open-parametrics is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with open-parametrics.  If not, see <http://www.gnu.org/licenses/>.
 */

package es.uah.cc.ie.parametrics;

import java.io.FileReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import weka.core.Attribute;
import weka.core.Instance;
import weka.core.Instances;

/**
 * A dataset including information on potential cost drivers.
 *
 * @author Miguel-Angel Sicilia
 */
public class ArffDataset extends Dataset {

    /**
     * The representation of the dataset in Weka form.
     */
    private Instances _dataset;

    /**
     *
     */
    private HashMap<CostDriver, Attribute> _costdrivermap;

    /**
     * The cost variable in the dataset.
     */
    private Attribute _costvariable = null;

     /**
     * Constructs the Dataset from a file name.
     */
     public ArffDataset(String label, String fileName){
        super(label);
        FileReader reader=null;
        try{
            reader = new FileReader(fileName);
            _dataset = new Instances(reader);
    	}catch (Exception e){
            System.out.println(e); System.exit(-3);
        }
       _costdrivermap = new HashMap<CostDriver, Attribute>();
    }

     /**
     * Constructs the Dataset from Instances.
     */
     public ArffDataset(String label, Instances data){
        super(label);
        assert(data != null);
        _dataset = data;
        _costdrivermap = new HashMap<CostDriver, Attribute>();
    }
      /**
       * Maps a cost driver to an attribute in the ARFF dataset.
       */
     public void mapCostDriver(CostDriver c, String attName){
         Attribute att = _dataset.attribute(attName);
         assert(att != null);
         _costdrivermap.put(c, att);
     }
      /**
       * Maps a cost driver to an attribute in the ARFF dataset.
       */
     public void mapCostVariable(Variable c, String attName){
         Attribute att = _dataset.attribute(attName);
         assert(att != null);
         _costvariable = att;
     }

     /**
      * Converts an ARFF instance to a list of cost driver values.
      * The cost driver to attribute mappings are used for the task.
      *
      * @param index The index of the instance to be converted (zero is the
      *  first index).
      * @return A list of cost driver values for the requested instance.
      * 
      */
     public List<CostDriverValue> getInstance(int index){
         // Get the instace in the dataset:
         Instance i = _dataset.instance(index);
         // Fill the list of cost driver values for the mapped cost drivers:
         List<CostDriverValue> ins = new LinkedList<CostDriverValue>();
         for (Iterator it = _costdrivermap.keySet().iterator(); it.hasNext();){
             CostDriver aux = (CostDriver)it.next();
             Attribute aux2 = _costdrivermap.get(aux);
             CostDriverValue cdv = new CostDriverValue(aux,
                                   i.value(aux2));
             ins.add(cdv);
         }
         return ins;
     }

    /**
     * Returns the number of instances.
     */
    public int getSize(){
        return _dataset.numInstances();
    }

    @Override
    public double[][] getXYSlice(CostDriver x, Variable y) {
        double [][] xydata;
        xydata = new double[getSize()][2];
        Attribute cd = (Attribute)_costdrivermap.get(x);
        for (int i =0; i<getSize(); i++){
            Instance ins = _dataset.instance(i);
            xydata[i][0]= ins.value(cd);
            xydata[i][1]= ins.value(_costvariable);
        }
        return xydata;
    }
    
    public Instances getInstances(){
        return _dataset;
    }
    
}
